package shop.up.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.up.common.constant.MqConst;
import shop.up.common.constant.RedisConst;
import shop.up.common.service.RabbitService;
import shop.up.common.util.HttpClientUtil;
import shop.up.model.enums.OrderStatus;
import shop.up.model.enums.ProcessStatus;
import shop.up.model.order.OrderDetail;
import shop.up.model.order.OrderInfo;
import shop.up.order.mapper.OrderDetailMapper;
import shop.up.order.mapper.OrderInfoMapper;
import shop.up.order.service.OrderService;

import java.util.*;

/**
 * 订单业务接口 {@link OrderServiceImpl}
 *
 * @author Kevin
 * @date 2022/7/26
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderService {

    @Autowired
    private OrderDetailMapper orderDetailMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitService rabbitService;

    @Value("${ware.url}")
    private String WARE_URL;

    /**
     * 保存订单
     * @param orderInfo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long saveOrderInfo(OrderInfo orderInfo) {
        // 保存订单基本信息 order_info
        // 计算订单总金额
        orderInfo.sumTotalAmount();
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        // 业务订单编号（在大型互联网生产系统，都会有一个分布式全局统一ID的服务来调用）
        String outTradeNo = "UPSHOP" + System.currentTimeMillis() + "" + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        orderInfo.setCreateTime(new Date());
        // 设置订单过期时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 1);
        orderInfo.setExpireTime(calendar.getTime());

        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());

        // 保存订单明细 order_detail
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        // 处理订单描述
        StringBuffer tradeBody = new StringBuffer();
        for (OrderDetail orderDetail : orderDetailList) {
            tradeBody.append(orderDetail.getSkuName() + " ");
        }
        if (tradeBody.toString().length() > 100){
            orderInfo.setTradeBody(tradeBody.toString().substring(0,100));
        }else {
            orderInfo.setTradeBody(tradeBody.toString());
        }

        // 保存订单信息，返回主键值
        baseMapper.insert(orderInfo);

        for (OrderDetail orderDetail : orderDetailList) {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
        }

        // 发送延迟队列，如果定时未支付，取消订单
        rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,
                MqConst.ROUTING_ORDER_CANCEL, orderInfo.getId(), MqConst.DELAY_TIME);

        return orderInfo.getId();
    }

    /**
     * 生产流水号
     * @param userId
     * @return
     */
    @Override
    public String getTradeNo(String userId) {
        // 定义key  user:1:tradeCode
        String tradeNoKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_TRADE_KEY_SUFFIX;
        // 定义一个流水号
        String tradeNo = UUID.randomUUID().toString().replace("-", "");
        redisTemplate.opsForValue().set(tradeNoKey, tradeNo);
        return tradeNo;
    }

    /**
     * 比较流水号
     * @param userId 获取缓存中的流水号
     * @param tradeCodeNo 面传递过来的流水号
     * @return
     */
    @Override
    public boolean checkTradeCode(String userId, String tradeCodeNo) {
        String tradeNoKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_TRADE_KEY_SUFFIX;
        String redisTradeNo = (String) redisTemplate.opsForValue().get(tradeNoKey);
        return tradeCodeNo.equals(redisTradeNo);
    }

    /**
     * 删除流水号
     * @param userId
     */
    @Override
    public void deleteTradeNo(String userId) {
        String tradeNoKey = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_TRADE_KEY_SUFFIX;
        // 删除数据
        redisTemplate.delete(tradeNoKey);
    }

    /**
     * 校验库存
     * @param skuId
     * @param skuNum
     * @return
     */
    @Override
    public boolean checkStock(Long skuId, Integer skuNum) {
        // 远程调用http://localhost:9001/hasStock?skuId=41&num=2
        String result = HttpClientUtil.doGet(WARE_URL + "/hasStock?skuId=" + skuId + "&num=" + skuNum);
        return "1".equals(result);
    }

    /**
     * 根据订单id查询订单信息
     * @param orderId
     * @return
     */
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        // 查询订单基本信息
        OrderInfo orderInfo = this.getById(orderId);
        // 查询订单明细
        QueryWrapper<OrderDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(queryWrapper);
        orderInfo.setOrderDetailList(orderDetailList);
        return orderInfo;
    }

    /**
     * 取消订单业务
     * @param orderId
     */
    @Override
    public void execExpiredOrder(Long orderId) {
        updateOrderStatus(orderId, ProcessStatus.CLOSED);
    }

    /**
     * 根据订单Id 修改订单的状态
     * @param orderId
     * @param processStatus
     */
    @Override
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setProcessStatus(processStatus.name());
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        baseMapper.updateById(orderInfo);
    }
}
